﻿using Microsoft.AspNetCore.Mvc;

namespace RuoVea.Swms.Server.Service
{
    /// <summary>
    /// 
    /// </summary>
    [ApiExplorerSettings(GroupName = "swms")]
    public class InventoryService : IApplicationService
    {
        private readonly SugarRepository<WmsProduct> _productRepo;
        private readonly SugarRepository<WmsStockIn> _stockInRepo;
        private readonly SugarRepository<WmsStockOut> _stockOutRepo;
        private readonly SugarRepository<WmsInventoryHistory> _historyRepo;
        private readonly LocationService _storageLocationService;

        private readonly ICurrentUser _currentUser;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="productRepo"></param>
        /// <param name="stockInRepo"></param>
        /// <param name="stockOutRepo"></param>
        /// <param name="historyRepo"></param>
        /// <param name="categoryRepo"></param>
        /// <param name="locationRepo"></param>
        /// <param name="currentUser"></param>
        public InventoryService(
            SugarRepository<WmsProduct> productRepo,
            SugarRepository<WmsStockIn> stockInRepo,
            SugarRepository<WmsStockOut> stockOutRepo,
            SugarRepository<WmsInventoryHistory> historyRepo,
            LocationService storageLocationService,
            ICurrentUser currentUser)
        {
            _productRepo = productRepo;
            _stockInRepo = stockInRepo;
            _stockOutRepo = stockOutRepo;
            _historyRepo = historyRepo;
            _currentUser = currentUser;
            _storageLocationService = storageLocationService;
        }


        #region 入库管理

        /// <summary>
        /// 入库记录分页查询
        /// </summary>
        public async Task<RestfulResult<PageResult<WmsStockIn>>> GetStockInPagesAsync(StockInPageParam data)
        {
            var restful = new RestfulResult<PageResult<WmsStockIn>>() { Code = CodeStatus.OK };
            data ??= new StockInPageParam { PageNo = 1, PageSize = 10 };

            var query = await _stockInRepo.AsQueryable()
                .WhereIF(data.StartDate.HasValue, u => u.InDate >= data.StartDate)
                .WhereIF(data.EndDate.HasValue, u => u.InDate <= data.EndDate)
                .WhereIF(data.ProductId > 0, u => u.ProductId == data.ProductId)
                .Includes(u => u.Product)
                .ToPageAsync(data.PageNo, data.PageSize);

            restful.Data = query;
            return restful;
        }

        /// <summary>
        /// 创建入库单
        /// </summary>
        [UnitOfWork]
        public async Task<RestfulResult> CreateStockInAsync(WmsStockIn data)
        {
            var restful = new RestfulResult() { Code = CodeStatus.BadRequest };

            // 检查产品是否存在
            var product = await _productRepo.GetFirstAsync(u => u.Id == data.ProductId);
            if (product == null)
            {
                restful.Message = "产品不存在";
                return restful;
            }

            // 设置操作人
            data.Operator = _currentUser.Name;
            data.InDate = DateTime.Now;
            var result = await _productRepo.Context.Ado.UseTranAsync(async () =>
            {
                // 开启事务
                var result1 = await _stockInRepo.InsertAsync(data);
                if (result1)
                {
                   
                    await _productRepo.UpdateAsync(product);
                    // 更新库存 - 使用更安全的方式
                    var affectedRows = await _productRepo.Context.Updateable<WmsProduct>()
                        .SetColumns(p => p.CurrentStock == p.CurrentStock + data.Quantity)
                        .Where(p => p.Id == data.ProductId)
                        .ExecuteCommandAsync();
                    if (affectedRows <= 0)
                    {
                        throw new Exception("库存更新失败");
                    }

                    // 更新位置容量
                    if (product.LocationId > 0)
                    {
                        var locationResult = await _storageLocationService.UpdateLocationCapacity(product.LocationId, data.Quantity);
                    }
                    // 记录库存变动历史
                    var newStock = product.CurrentStock + data.Quantity;
                    // 记录库存变动历史
                    await RecordInventoryHistory(data.ProductId, "IN", data.Quantity, newStock, data.Operator);
                }
                else
                {
                    throw new Exception("入库失败");
                }
            });

            restful.Data = result.IsSuccess;
            restful.Code = result.IsSuccess ? CodeStatus.OK : CodeStatus.BadRequest;
            restful.Message = result.IsSuccess ? "入库成功" : result.ErrorMessage;

            return restful;
        }

        #endregion

        #region 出库管理

        /// <summary>
        /// 出库记录分页查询
        /// </summary>
        public async Task<RestfulResult<PageResult<WmsStockOut>>> GetStockOutPagesAsync(StockOutPageParam data)
        {
            var restful = new RestfulResult<PageResult<WmsStockOut>>() { Code = CodeStatus.OK };
            data ??= new StockOutPageParam { PageNo = 1, PageSize = 10 };

            var query = await _stockOutRepo.AsQueryable()
                .WhereIF(data.StartDate.HasValue, u => u.OutDate >= data.StartDate)
                .WhereIF(data.EndDate.HasValue, u => u.OutDate <= data.EndDate)
                .WhereIF(data.ProductId > 0, u => u.ProductId == data.ProductId)
                .Includes(u => u.Product)
                .ToPageAsync(data.PageNo, data.PageSize);

            restful.Data = query;
            return restful;
        }

        /// <summary>
        /// 创建出库单
        /// </summary>
        [UnitOfWork]
        public async Task<RestfulResult> CreateStockOutAsync(WmsStockOut data)
        {
            var restful = new RestfulResult() { Code = CodeStatus.BadRequest };

            // 检查产品是否存在
            var product = await _productRepo.GetFirstAsync(u => u.Id == data.ProductId);
            if (product == null)
            {
                restful.Message = "产品不存在";
                return restful;
            }

            // 检查库存是否充足
            if (product.CurrentStock < data.Quantity)
            {
                restful.Message = "库存不足";
                return restful;
            }

            // 设置操作人
            data.Operator = _currentUser.Name;
            data.OutDate = DateTime.Now;

            var result = _stockOutRepo.Context.Ado.UseTran(async () =>
            {
                // 开启事务
                var result1 = await _stockOutRepo.InsertAsync(data);
                if (result1)
                {
                    // 更新库存
                    product.CurrentStock -= data.Quantity;
                    await _productRepo.UpdateAsync(product);

                    // 更新位置容量
                    if (product.LocationId > 0)
                    {
                        await _storageLocationService.UpdateLocationCapacity(product.LocationId, -data.Quantity);
                    }

                    // 记录库存变动历史
                    await RecordInventoryHistory(data.ProductId, "OUT", data.Quantity, product.CurrentStock, data.Operator);
 
                }
                else
                    throw new Exception("出库失败");
            });

            restful.Data = result.IsSuccess;
            restful.Code = result.IsSuccess ? CodeStatus.OK : CodeStatus.BadRequest;
            restful.Message = result.IsSuccess ? "出库成功" : result.ErrorMessage;

            return restful;
        }

        #endregion

        #region 库存管理

        /// <summary>
        /// 获取当前库存
        /// </summary>
        public async Task<RestfulResult<List<WmsProduct>>> GetCurrentInventory()
        {
            var restful = new RestfulResult<List<WmsProduct>>() { Code = CodeStatus.OK };

            var products = await _productRepo.GetListAsync(u => u.CurrentStock > 0);

            restful.Data = products;
            return restful;
        }

        /// <summary>
        /// 获取库存变动历史
        /// </summary>
        public async Task<RestfulResult<List<WmsInventoryHistory>>> GetInventoryHistory(long productId)
        {
            var restful = new RestfulResult<List<WmsInventoryHistory>>() { Code = CodeStatus.OK };

            var history = await _historyRepo.AsQueryable()
                .Where(u => u.ProductId == productId)
                .OrderByDescending(u => u.ChangeDate)
                .ToListAsync();

            restful.Data = history;
            return restful;
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 记录库存变动历史
        /// </summary>
        private async Task RecordInventoryHistory(long productId, string changeType, int quantity, int currentStock, string operatorName)
        {
            var history = new WmsInventoryHistory
            {
                Id = IdGenerator.Id,

                ProductId = productId,
                ChangeDate = DateTime.Now,
                ChangeType = changeType,
                Quantity = quantity,
                Operator = operatorName,
                Creator=_currentUser.UserId,
                CurrentStock = currentStock
            };

            bool isSuccess = await _historyRepo.InsertAsync(history);
            if (!isSuccess)
                throw new Exception("记录库存变动历史失败");
        }

        #endregion
    }
}